package com.authine.cloudpivot.ext.service.impl;

import cn.hutool.core.map.MapBuilder;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.cola.dto.RequestContext;
import com.alibaba.cola.dto.SingleResponse;
import com.alibaba.fastjson.JSON;
import com.authine.cloudpivot.ext.applicationservice.base.ApplicationBaseService;
import com.authine.cloudpivot.ext.constants.AppConst;
import com.authine.cloudpivot.ext.constants.ModelConst;
import com.authine.cloudpivot.ext.constants.ServiceUrlConst;
import com.authine.cloudpivot.ext.dto.*;
import com.authine.cloudpivot.ext.dto.system.OrganizationDto;
import com.authine.cloudpivot.ext.dto.system.UserDto;
import com.authine.cloudpivot.ext.enums.order.*;
import com.authine.cloudpivot.ext.enums.order.transfer.OrderType;
import com.authine.cloudpivot.ext.service.ContractService;
import com.authine.cloudpivot.ext.utils.*;
import com.authine.cloudpivot.ext.utils.system.UserUtils;
import com.authine.mvp.app.launcher.common.TableHelper;
import com.authine.mvp.app.launcher.domain.SelectorFormat;
import com.authine.mvp.app.launcher.domain.utills.ApplicationContextUtils;
import com.authine.mvp.app.launcher.dto.bo.response.BO;
import com.authine.mvp.app.launcher.gateway.bo.BOValidatedAndFormatService;
import com.authine.mvp.app.launcher.utils.JsonParseObject;
import com.authine.mvp.app.org.dto.domainmodel.UnitType;
import lombok.extern.slf4j.Slf4j;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
public class ContractServiceImpl extends ApplicationBaseService implements ContractService {

    private final NamedParameterJdbcTemplate jdbcTemplate = ApplicationContextUtils.getBean(NamedParameterJdbcTemplate.class);
    private final TableHelper tableHelper = ApplicationContextUtils.getBean(TableHelper.class);
    private BOValidatedAndFormatService bOValidatedAndFormatService = ApplicationContextUtils.getBean(BOValidatedAndFormatService.class);

    /**
     * 保存代购合同
     * cn/gomro/core/bizes/contract/service/impl/ContractOrderService.createContract
     *
     * @param contractIntention
     * @return
     */
    @Override
    public SingleResponse<BO> saveIntentionContract(ContractOrderIntentionDto contractIntention) {
        if (null == contractIntention) {
            throw new RuntimeException("代购意向不存在");
        }

        Assert.notNull(contractIntention.getId(), "代购意向ID为null");

        Map<String, Object> contractIntentionEntity = selectModelById(contractIntention.getId(), ModelConst.T_CONTRACT_ORDER_INTENTION);

        Assert.notNull(contractIntentionEntity, "代购意向不存在");

        //verify: 代购意向必须为未启动状态
        Assert.isTrue(ContractClauseStatusEnum.NEW.name().equals(contractIntentionEntity.get("contract_intention_status")), "只有未启动状态才可以修改");

        Assert.notNull(contractIntention.getVendorOrganizationId(), "请选择供应商");

        //create goods
        List<Map<String, Object>> contractGoodsList = createContractGoods(contractIntention.getId(), contractIntention.getContractGoods());

//        final BigDecimal[] goodsAmount = {BigDecimal.ZERO};
//        contractGoodsList.forEach(goods -> goodsAmount[0] = BigDecimalUtils.add(goodsAmount[0], BigDecimalUtils.isNull(goods.get("total"))));

        //create clause
        createContractClause(contractIntention.getId(), contractIntention.getContractClause(), contractIntention.getAmount());

        //update intention
        Map<String, Object> param = new HashMap<>();
        param.put("id", contractIntentionEntity.get("id"));
        param.put("amount", contractIntention.getAmount());
        param.put("memo", contractIntention.getMemo());
        param.put("contract_content", contractIntention.getContractContent());
        param.put("vendor_organization_id", contractIntention.getVendorOrganizationId());
        param.put("vendor_organization_name", contractIntention.getVendorOrganizationId().getName());
        return BoServiceUtils.updateMainBo(ModelConst.T_CONTRACT_ORDER_INTENTION, param);
    }

    /**
     * 创建代购意向
     * cn/gomro/core/bizes/contract/service/impl/ContractOrderService.save
     *
     * @param contractIntention
     * @return
     */
    @Override
    public SingleResponse<BO> saveIntention(ContractOrderIntentionDto contractIntention) {
        if (null == contractIntention) {
            throw new RuntimeException("代购意向不存在");
        }
        SelectorFormat memberId = getSelectorFormat(null, UnitType.USER);
        contractIntention.setMemberId(memberId);
        contractIntention.setMemberName(memberId.getName());
        contractIntention.setContractIntentionStatus(ContractClauseStatusEnum.NEW.name());

        Map<String, Object> result = ContractOrderIntentionDto.voToEntity(contractIntention);
        log.info("创建代购意向转换 result：" + result);
        return BoServiceUtils.createBo(ModelConst.T_CONTRACT_ORDER_INTENTION, Collections.singletonList(result));
    }

    /**
     * 保存并提交代购合同
     * cn/gomro/core/bizes/contract/service/impl/ContractOrderService.createSubmitContract
     *
     * @param contractIntention
     * @return
     */
    @Override
    public SingleResponse<BO> createSubmitContract(ContractOrderIntentionDto contractIntention) {
        saveIntentionContract(contractIntention);
        return submitIntentionContract(Collections.singletonList(contractIntention.getId()));
    }

    /**
     * 确认付款条款，并生成代购商品源，和客户订单（包含一个供应商订单和很多订单商品）
     * cn/gomro/core/bizes/contract/service/impl/ContractOrderService.confirmContract
     *
     * @param intentionId
     * @return
     */
    @Override
    public SingleResponse<BO> confirmIntentionContract(String intentionId) {
        Assert.notNull(intentionId, "代购意向ID必填");
        Map<String, Object> contractIntention = selectModelById(intentionId, ModelConst.T_CONTRACT_ORDER_INTENTION);
        Assert.notNull(contractIntention, "未查到对应的的代购意向");
        Assert.isTrue(ContractClauseStatusEnum.DELIVERED.name().equals(contractIntention.get("contract_intention_status")), "只有待确认才可确认");

        //根据代购商品创建商品库
//        List<Map<String, Object>> goodsContractList = generateGoods(intentionId);
//
//        List<List<String>> generateOrderResults = generateOrder(contractIntention, goodsContractList);

        //调用订单中心,创建发货单并发货
        String url = HttpClients.getUrl(AppConst.ORDER_CENTER, ServiceUrlConst.CREATED_ORDER_AND_DELIVERY_URL);
        log.info("创建发货单并发货 param:" + JSON.toJSONString(intentionId));
        String re = HttpClients.execute(url, intentionId);
        log.info("创建发货单并发货 result:" + re);
        if(StringUtils.isNotBlank(re)&&!JSON.parseObject(re, SingleResponse.class).isSuccess()){
            throw new RuntimeException(JSON.parseObject(re, SingleResponse.class).getErrMessage());
        }
        Map<String, Object> contractIntentionParam = new HashMap<>();
        contractIntentionParam.put("contract_intention_status", ContractClauseStatusEnum.DONE.name());
        contractIntentionParam.put("id", contractIntention.get("id"));
        SingleResponse<BO> result = BoServiceUtils.updateMainBo(ModelConst.T_CONTRACT_ORDER_INTENTION, contractIntentionParam);

        //根据客户订单ID查询订单商品列表
//        if (!CollectionUtils.isEmpty(generateOrderResults)) {
//            String customerOrderIdsSql = generateOrderResults.get(0).stream().map(s -> "\'" + s + "\'").collect(Collectors.joining(", "));
//            String customerOrderSql = "select * from " + getTableName(ModelConst.T_ORDER_CUSTOMER) + " where deleted ='0' and id in (" + customerOrderIdsSql + ")";
//            List<Map<String, Object>> orderGoodsList = jdbcTemplate.queryForList(customerOrderSql, new HashMap<>());
//            //TODO 创建合同记录
//            //createContractTrade(orderGoodsList);
//        }
        return result;
    }

    /**
     * 提交代购合同
     * cn/gomro/core/bizes/contract/service/impl/ContractOrderService.submit
     *
     * @param ids
     */
    @Override
    public SingleResponse<BO> submitIntentionContract(Collection<String> ids) {
        List<Map<String, Object>> intentionParams = new ArrayList<>();
        if (CollectionUtils.isEmpty(ids)) {
            throw new RuntimeException("参数不能为空");
        }
        String idsSql = ids.stream().map(s -> "\'" + s + "\'").collect(Collectors.joining(", "));
        String clauseSql = "select count(distinct contract_intention_id) from " + getTableName(ModelConst.T_CONTRACT_CLAUSE) + " where deleted ='0' and contract_intention_id in (" + idsSql + ")";
        Integer l = 0;
        try {
            l = jdbcTemplate.queryForObject(clauseSql, new HashMap<>(), Integer.class);
        } catch (DataAccessException e) {
            e.printStackTrace();
        }
        if (0 == l || ids.size() != l) {
            throw new RuntimeException("请创建代购合同");
        }
        String goodsSql = "select count(*) from " + getTableName(ModelConst.T_CONTRACT_GOODS) + " where deleted ='0' and contract_intention_id in (" + idsSql + ")";
        Integer g = 0;
        try {
            g = jdbcTemplate.queryForObject(clauseSql, new HashMap<>(), Integer.class);
        } catch (DataAccessException e) {
            e.printStackTrace();
        }
        if (0 == g || ids.size() != g) {
            throw new RuntimeException("请创建代购合同");
        }

        String intentionSql = "select * from " + getTableName(ModelConst.T_CONTRACT_ORDER_INTENTION) + " where deleted ='0' and id in (" + idsSql + ")";
        List<Map<String, Object>> intentionList = jdbcTemplate.queryForList(intentionSql, new HashMap<>());

        for (Map<String, Object> contractIntentionEntity : intentionList) {
            if (!contractIntentionEntity.get("contract_intention_status").equals(ContractClauseStatusEnum.NEW.name())) {
                throw new RuntimeException("只有未启动状态才可以提交");
            }
            Map<String, Object> intentionParam = new HashMap<>();
            intentionParam.put("contract_intention_status", ContractClauseStatusEnum.DELIVERED.name());
            intentionParam.put("id", contractIntentionEntity.get("id"));
            intentionParams.add(intentionParam);
        }
        return BoServiceUtils.updateMainBo(ModelConst.T_CONTRACT_ORDER_INTENTION, intentionParams);
    }

    /**
     * 构建客户订单并进行创建和发货记录 (代购下单)
     *
     * @param intention         代购意向
     * @param goodsContractList 代购商品
     * @return
     */
    public List<List<String>> generateOrder(Map<String, Object> intention, List<Map<String, Object>> goodsContractList) {
        List<List<String>> results = new ArrayList<>();
        Assert.notNull(intention, "代购意向ID必填");
        Assert.isTrue(!CollectionUtils.isEmpty(goodsContractList), "未查到对应的的代购商品");

        String clauseSql = "select * from " + getTableName(ModelConst.T_CONTRACT_CLAUSE) + " where deleted ='0' and contract_intention_id = " + intention.get("id");
        List<Map<String, Object>> contractClauseList = jdbcTemplate.queryForList(clauseSql, new HashMap<>());
        Assert.isTrue(!CollectionUtils.isEmpty(contractClauseList), "未查到对应的代购条款");

        //代购供应商组织
//        Organization vendorOrganization = organizationApi.get(intention.get("vendor_organization_id")).getDataErrorThrow();

        //获取当前操作人收货地址
        List<Map<String, Object>> deliverAddressList = getAddress(null, true, null);
        if(CollectionUtils.isEmpty(deliverAddressList)){
            throw new RuntimeException("当前登录人缺少收货地址，请到个人中心添加，并设置为默认地址");
        }

        for (Map<String, Object> contractClause : contractClauseList) {
            Map<String, Object> customerOrder = this.buildCustomerOrder(deliverAddressList, goodsContractList, BigDecimalUtils.isNull(contractClause.get("clause_ratio")));
//            SingleResponse<BO> coRes = BoServiceUtils.createBo(ModelConst.T_ORDER_CUSTOMER, Collections.singletonList(customerOrder));
            BoResultFormat.initSys(RequestContext.getCorpLoginId(), customerOrder);
            int ci = JdbcTemplateUtils.builder(AppConst.ORDER_CENTER, ModelConst.T_ORDER_CUSTOMER).putFieldAndVal(customerOrder).insert();
            if(ci>0){
                throw new RuntimeException("客户订单保存失败");
            }
            customerOrder.put("id", customerOrder.get("id"));

            Map<String, Object> vendorOrder = this.buildVendorOrder(customerOrder, intention);
            BoResultFormat.initSys(RequestContext.getCorpLoginId(), vendorOrder);
            int vi = JdbcTemplateUtils.builder(AppConst.ORDER_CENTER, ModelConst.T_ORDER_VENDOR).putFieldAndVal(vendorOrder).insert();
//            SingleResponse<BO> voRes = BoServiceUtils.createBo(ModelConst.T_ORDER_VENDOR, Collections.singletonList(vendorOrder));
            if(vi>0){
                throw new RuntimeException("供应商订单保存失败");
            }
            vendorOrder.put("id", vendorOrder.get("id"));
            List<Map<String, Object>> orderGoodsList = this.buildOrderGoods(goodsContractList, contractClause, vendorOrder);
            for (Map<String, Object> orderGoods : orderGoodsList) {
                //订单商品关联表创建
                Map<String, Object> relation = new HashMap<>();
                BoResultFormat.initSys(RequestContext.getCorpLoginId(), relation);
                JdbcTemplateUtils.builder(AppConst.ORDER_CENTER, ModelConst.T_ORDER_GOODS_RELATION).putFieldAndVal(relation).insert();
                //客户订单商品创建
                BoResultFormat.initSys(RequestContext.getCorpLoginId(), orderGoods);
                orderGoods.put("order_customer_goods_status", com.authine.cloudpivot.ext.enums.order.OrderGoodsStatusEnum.UpcomingDelivery.name());
                orderGoods.put("relation_id", relation.get("id"));
                JdbcTemplateUtils.builder(AppConst.ORDER_CENTER, ModelConst.T_ORDER_CUSTOMER_GOODS).putFieldAndVal(orderGoods).insert();
                String orderCustomerGoodsId = (String) orderGoods.get("id");
                //供应商订单商品创建
                BoResultFormat.initSys(RequestContext.getCorpLoginId(), orderGoods);
                orderGoods.remove("order_customer_goods_status");
                orderGoods.put("order_vendor_goods_status", com.authine.cloudpivot.ext.enums.order.OrderGoodsStatusEnum.UpcomingDelivery.name());
                JdbcTemplateUtils.builder(AppConst.ORDER_CENTER, ModelConst.T_ORDER_VENDOR_GOODS).putFieldAndVal(orderGoods).insert();
                String orderVendorGoodsId = (String) orderGoods.get("id");

                //创建代购发货
                OrderTraceDto dto = new OrderTraceDto();
                dto.setOrderVendorGoodsIds(Collections.singletonList(orderVendorGoodsId));
                dto.setOrderVendorId((String) vendorOrder.get("id"));
                dto.setLogistics("代购");
                dto.setWaybills(Collections.singletonList(new String("代购")));
                dto.setFreight(BigDecimal.ZERO);
                dto.setQuantitys(Collections.singletonList(BigDecimalUtils.isNull(orderGoods.get("quantity"))));
                //调用订单中心供应商发货接口
//                String url = HttpClients.getUrl(AppConst.ORDER_CENTER, ServiceUrlConst.VENDOR_DELIVERY_LOGISTICS_URL);
//                log.info("供应商发货 param:" + JSON.toJSONString(dto));
//                String result = HttpClients.execute(url, dto);
//                log.info("供应商发货 result:" + result);
            }
            //生成转采订单
            contractToTransferOrder(customerOrder, vendorOrder);
            //更新代购条款表客户订单ID
            JdbcTemplateUtils.builder(ModelConst.T_CONTRACT_CLAUSE).putFieldAndVal("customer_order_id", customerOrder.get("id"))
                    .putFieldAndVal("order_customer_status", OrderCustomerStatusEnum.DoneDelivery.name()).eq("id", contractClause.get("id")).update();
        }
        return results;
    }

    /**
     * 代购订单-》转采订单
     *
     * @param orderVendor
     * @return
     */
    public void contractToTransferOrder(Map<String, Object> orderCustomer, Map<String, Object> orderVendor) {
        if (CollectionUtils.isEmpty(orderCustomer)||CollectionUtils.isEmpty(orderVendor)) {
            return;
        }
        //判断是否为虚拟供应商
        List<Map<String, Object>> voList = Collections.singletonList(orderVendor);
        if (!CollectionUtils.isEmpty(voList)) {
            Map<String, Object> transferOrder = new HashMap<>();
            String platformId = null;
            String platformName = null;
            String orderType = OrderType.Contract.name();
            List<SelectorFormat> memberIds = Objects.isNull(orderCustomer.get("place_order_user_id"))?null:JsonParseObject.parseObject((String) orderCustomer.get("place_order_user_id"), SelectorFormat.class);
            transferOrder.put("member_id", CollectionUtils.isEmpty(memberIds)?null:memberIds.get(0));
            transferOrder.put("cloud_order_id", orderCustomer.get("id"));
            transferOrder.put("user_name", CollectionUtils.isEmpty(memberIds)?null:memberIds.get(0).getName());
            List<SelectorFormat> organizationIds = Objects.isNull(orderCustomer.get("organization_id"))?null:JsonParseObject.parseObject((String) orderCustomer.get("place_order_user_id"), SelectorFormat.class);
            transferOrder.put("organization_id", CollectionUtils.isEmpty(organizationIds)?null:organizationIds.get(0));
            transferOrder.put("organization_name", CollectionUtils.isEmpty(organizationIds)?null:organizationIds.get(0).getName());
            transferOrder.put("tax_rate", ObjectUtil.defaultIfNull(orderCustomer.get("tax_rate"), BigDecimal.ZERO));
            transferOrder.put("total", ObjectUtil.defaultIfNull(orderCustomer.get("total"), BigDecimal.ZERO));
            transferOrder.put("pre_total", ObjectUtil.defaultIfNull(orderCustomer.get("pretax_total"), BigDecimal.ZERO));
            transferOrder.put("amount", ObjectUtil.defaultIfNull(orderCustomer.get("amount"), BigDecimal.ZERO));
            transferOrder.put("pre_amount", ObjectUtil.defaultIfNull(orderCustomer.get("pretax_amount"), BigDecimal.ZERO));
            transferOrder.put("receiver", orderCustomer.get("receiver"));
            transferOrder.put("phone", orderCustomer.get("phone"));
            transferOrder.put("postal", orderCustomer.get("postal"));
            transferOrder.put("address", orderCustomer.get("address"));
            transferOrder.put("order_type", orderType);
            transferOrder.put("is_contract", StringUtils.isNotBlank(orderType) && orderType.equals(OrderType.Contract.name()) ? true : false);
            transferOrder.put("transfer_order_status", OrderCustomerStatusEnum.DoneDelivery.name());
            transferOrder.put("erp_po", orderCustomer.get("erp_po"));
            if (!CollectionUtils.isEmpty(organizationIds)) {
                Map<String, Object> organization = JdbcTemplateUtils.builder(AppConst.SYSTEM_MANAGEMENT, ModelConst.T_ORGANIZATION).eq("id", organizationIds.get(0).getId()).queryForMap();
                if (!CollectionUtils.isEmpty(organization)) {
                    platformId = Objects.isNull(organization.get("platform_id")) ? null : JsonParseObject.parseObject((String) organization.get("platform_id"), SelectorFormat.class).get(0).getId();
                    platformName = CollectionUtils.isEmpty(organization) ? null : (String) organization.get("platform_name");
                    transferOrder.put("platform_id", platformId);
                    transferOrder.put("platform_name", platformName);
                }
            }
            SingleResponse<BO> transferOrderBO = BoServiceUtils.createBo(ModelConst.T_TRANSFER_ORDER, Collections.singletonList(transferOrder));
//            JdbcTemplateUtils.builder(AppConst.ORDER_CENTER, ModelConst.T_TRANSFER_ORDER).putFieldAndVal(transferOrder).insert();
            List<Map<String, Object>> orderGoodsList = new ArrayList<>();
            for (Map<String, Object> voe : voList) {
                orderGoodsList = JdbcTemplateUtils.builder(AppConst.ORDER_CENTER, ModelConst.T_ORDER_CUSTOMER_GOODS).selectField("*").eq("order_customer_id", voe.get("order_customer_id")).queryForList();
                SelectorFormat vendorId = ObjectUtil.defaultIfNull(JSON.parseObject((String) voe.get("organization_id"), SelectorFormat.class), null);
                for (Map<String, Object> oge : orderGoodsList) {
                    Map<String, Object> transferOrderGoods = MapBuilder.create(new HashMap<String, Object>())
                            //状态转换
                            .put("transfer_order_goods_status", oge.get("order_customer_goods_status"))
                            .put("cloud_order_goods_id", oge.get("id"))
                            .put("vendor_id", JSON.toJSONString(vendorId))
                            .put("vendor_name", ObjectUtil.defaultIfNull(vendorId.getName(), null))
                            .put("category", oge.get("category"))
                            .put("brand", oge.get("brand"))
                            .put("name", oge.get("name"))
                            .put("model", oge.get("model"))
                            .put("spec", oge.get("spec"))
                            .put("sku", oge.get("sku"))
                            .put("memo", oge.get("description"))
                            .put("unit", oge.get("unit"))
                            .put("delivery", BigDecimalUtils.isNull(oge.get("delivery")).intValue())
                            .put("num", oge.get("quantity"))
                            .put("price", BigDecimalUtils.round(BigDecimalUtils.isNull(oge.get("price")), 16))
                            .put("pre_price", BigDecimalUtils.round(BigDecimalUtils.isNull(oge.get("pretax_price")), 16))
                            .put("freight", BigDecimalUtils.round(BigDecimalUtils.isNull(oge.get("freight")), 2))
                            .put("tax_rate",  BigDecimalUtils.round(BigDecimalUtils.isNull(oge.get("tax_rate")), 2))
                            .put("total", BigDecimalUtils.round(BigDecimalUtils.isNull(oge.get("total")), 2))
                            .put("pre_total", BigDecimalUtils.round(BigDecimalUtils.isNull(oge.get("pretax_total")), 2))
                            .put("amount", BigDecimalUtils.round(BigDecimalUtils.isNull(oge.get("amount")), 2))
                            .put("not_purchase", false)
                            .put("pre_amount", BigDecimalUtils.round(BigDecimalUtils.isNull(oge.get("pretax_amount")), 2)).build();
                    //询价商品id
                    if (null != oge.get("relation_id")) {
                        Map<String, Object> orderGoodsRelation = JdbcTemplateUtils.builder(AppConst.ORDER_CENTER, ModelConst.T_ORDER_GOODS_RELATION).selectField("*")
                                .eq("id", oge.get("relation_id")).queryForMap();
                        if (orderGoodsRelation != null) {
                            transferOrderGoods.put("inquiry_id", orderGoodsRelation.get("inquiry_td"));
                        }
                    }
                    transferOrderGoods.put("remark_message", "");
                    transferOrderGoods.put("platform_name", platformName);
                    transferOrderGoods.put("order_type", orderType);
                    transferOrderGoods.put("cloud_order_id", orderCustomer.get("id"));
                    transferOrderGoods.put("user_name", CollectionUtils.isEmpty(memberIds)?null:memberIds.get(0).getName());
                    transferOrderGoods.put("organization_name", CollectionUtils.isEmpty(organizationIds)?null:organizationIds.get(0).getName());
                    transferOrderGoods.put("transfer_order_id", transferOrderBO.getData().getBizObjectId());
                    BoServiceUtils.createBo(ModelConst.T_TRANSFER_ORDER_GOODS, Collections.singletonList(transferOrderGoods));
//                    JdbcTemplateUtils.builder(AppConst.ORDER_CENTER, ModelConst.T_TRANSFER_ORDER_GOODS).putFieldAndVal(transferOrderGoods).insert();
                }
            }
            JdbcTemplateUtils.builder(ModelConst.T_TRANSFER_ORDER).putFieldAndVal("account_period",
                    orderGoodsList.get(0).get("customer_account_period")).eq("id", transferOrderBO.getData().getBizObjectId()).update();
        }
    }

    /**
     * 初始化订单商品
     *
     * @param goodsContractList
     * @param contractClause
     * @param vendorOrder
     * @return
     */
    private List<Map<String, Object>> buildOrderGoods(List<Map<String, Object>> goodsContractList, Map<String, Object> contractClause, Map<String, Object> vendorOrder) {

        List<Map<String, Object>> orderGoodsList = new ArrayList<>();
        for (Map<String, Object> goodsContract : goodsContractList) {
            Object goodsId = goodsContract.get("id");
            Map<String, Object> orderGoods = MapBuilder.create(new HashMap<String, Object>()).putAll(goodsContract).build();
            orderGoods.remove("id");
            orderGoods.remove("num");

            BigDecimal num = BigDecimalUtils.mul(BigDecimalUtils.isNull(goodsContract.get("num")), BigDecimalUtils.isNull(contractClause.get("clause_ratio")));
            orderGoods.put("quantity", num);
            orderGoods.put("goods_src", GoodsSrcEnum.Contract.name());
            orderGoods.put("goods_id", goodsId);
            orderGoods.put("category", "");
            orderGoods.put("images", "[]");
            orderGoods.put("client_order_goods_id", "");
//            orderGoods.put("contract_goods_id", goodsContract.get("contract_goods_id"));
            orderGoods.put("order_vendor_id", vendorOrder.get("id"));
            orderGoods.put("order_customer_id", vendorOrder.get("order_customer_id"));
            SelectorFormat customerOrganizationIdSF = getSelectorFormat(null, UnitType.DEPARTMENT);
            orderGoods.put("customer_organization_id", JSON.toJSONString(customerOrganizationIdSF));
            orderGoods.put("customer_organization_name", customerOrganizationIdSF.getName());
            SelectorFormat vendorOrganizationIdSF = Objects.isNull(vendorOrder.get("vendor_organization_id")) ? null : JSON.parseObject((String) vendorOrder.get("vendor_organization_id"), SelectorFormat.class);
            orderGoods.put("vendor_organization_id", Objects.isNull(vendorOrganizationIdSF)?null:JSON.toJSONString(vendorOrganizationIdSF));
            orderGoods.put("vendor_organization_name", Objects.isNull(vendorOrganizationIdSF)?null:vendorOrganizationIdSF.getName());
            orderGoods.put("confirm_order_time", new Date());
            orderGoods.put("place_order_time", new Date());
            //客户订单商品和供应商订单商品来源类型是 代购 | VMI | 市场,取结算账户账期
            Integer accountPeriod = getStatementCycle(null);
            orderGoods.put("customer_account_period", accountPeriod);
            orderGoods.put("vendor_account_period", accountPeriod);
            orderGoodsList.add(orderGoods);
        }
        return orderGoodsList;
    }

    /**
     * 初始化供应商订单
     *
     * @param customerOrder
     * @param intention
     * @return
     */
    private Map<String, Object> buildVendorOrder(Map<String, Object> customerOrder, Map<String, Object> intention) {
        Map<String, Object> vendorOrder = new HashMap<>();
        vendorOrder.put("order_customer_id", customerOrder.get("id"));
//        vendorOrder.put("vendor_id", vendorOrganization.getId());
        List<SelectorFormat> vendorOrganizationIds = JsonParseObject.parseObject((String) intention.get("vendor_organization_id"), SelectorFormat.class);
        vendorOrder.put("organization_id", !CollectionUtils.isEmpty(vendorOrganizationIds)?vendorOrganizationIds.get(0):null);
        vendorOrder.put("organization_name", !CollectionUtils.isEmpty(vendorOrganizationIds)?vendorOrganizationIds.get(0).getName():null);
        vendorOrder.put("tax_rate", 0.0);
        vendorOrder.put("tax_rate_freight", 0.0);
        vendorOrder.put("tax_payable", 0.0);
        vendorOrder.put("tax_payable_freight", 0.0);
        vendorOrder.put("pretax_freight", 0.0);
        vendorOrder.put("freight", 0.0);
        vendorOrder.put("memo", intention.get("memo"));
        vendorOrder.put("account_period", 0);
        customerOrder.put("order_vendor_status", OrderVendorStatusEnum.UpcomingDelivery.name());
        customerOrder.put("after_sale", "未售后");
        customerOrder.put("confirm_order_time", new Date());
        return vendorOrder;
    }

    /**
     * 初始化客户订单
     *
     * @param deliverAddressList
     * @return
     */
    private Map<String, Object> buildCustomerOrder(List<Map<String, Object>> deliverAddressList, List<Map<String, Object>> goodsContractList, BigDecimal clauseRatio) {
        Map<String, Object> memberDeliverAddress = new HashMap<>();
        if (!CollectionUtils.isEmpty(deliverAddressList)) {
            memberDeliverAddress = deliverAddressList.get(0);
        }
        Double total = goodsContractList.stream().mapToDouble(t -> BigDecimalUtils.isNull(t.get("total")).doubleValue()).sum();
        Double pretaxTotal = goodsContractList.stream().mapToDouble(t -> BigDecimalUtils.calculateTaxBefore(BigDecimalUtils.isNull(t.get("total")),
                BigDecimalUtils.mul(BigDecimalUtils.isNull(t.get("tax_rate")), new BigDecimal("100"))).doubleValue()).sum();
        Map<String, Object> customerOrder = new HashMap<>();
        customerOrder.put("total", BigDecimalUtils.round(BigDecimalUtils.mul(new BigDecimal(total), clauseRatio), 2));
        customerOrder.put("pretax_total", BigDecimalUtils.round(BigDecimalUtils.mul(new BigDecimal(pretaxTotal), clauseRatio), 2));
        customerOrder.put("amount", BigDecimalUtils.round(BigDecimalUtils.mul(new BigDecimal(total), clauseRatio), 2));
        customerOrder.put("pre_amount", BigDecimalUtils.round(BigDecimalUtils.mul(new BigDecimal(pretaxTotal), clauseRatio), 2));
        SelectorFormat currentUser = bOValidatedAndFormatService.getCurrentUser();
        customerOrder.put("place_order_user_id", currentUser);
        customerOrder.put("place_order_fullname", currentUser.getName());
        SelectorFormat currentDept = bOValidatedAndFormatService.getCurrentDepartment();
        customerOrder.put("organization_id", currentDept);
        customerOrder.put("organization_name", currentDept.getName());
        customerOrder.put("erp_pp", null);
        customerOrder.put("pretax_freight", 0.0);
        customerOrder.put("tax_rate_freight", 0.0);
        customerOrder.put("tax_payable_freight", 0.0);
        customerOrder.put("freight", 0.0);
        customerOrder.put("tax_rate", 0.0);
        customerOrder.put("tax_payable", 0.0);
        customerOrder.put("receiver", Objects.toString(memberDeliverAddress.get("receiver_name"), ""));
        customerOrder.put("phone", Objects.toString(memberDeliverAddress.get("mobile"), ""));
        customerOrder.put("postal", Objects.toString(memberDeliverAddress.get("post"), ""));
        customerOrder.put("address", Objects.toString(memberDeliverAddress.get("address"), ""));
        customerOrder.put("order_customer_status", OrderCustomerStatusEnum.UpcomingDelivery.name());
        customerOrder.put("payment_method", PaymentMethodEnum.Credit.name());
        customerOrder.put("type", OrderTypeEnum.ContractOrder.name());
        customerOrder.put("after_sale", "未售后");
        customerOrder.put("enabled", true);
        customerOrder.put("place_order_time", new Date());
        return customerOrder;
    }

    /**
     * 构建订单商品
     * @param intentionId
     * @return
     */
    public List<Map<String, Object>> generateGoods(String intentionId) {
        String goodsSql = "select * from " + getTableName(ModelConst.T_CONTRACT_GOODS) + " where deleted ='0' and contract_intention_id = " + intentionId;
        List<Map<String, Object>> contractGoodsList = jdbcTemplate.queryForList(goodsSql, new HashMap<>());
        Assert.isTrue(!CollectionUtils.isEmpty(contractGoodsList), "未获取到对应的代购商品");
        List<Map<String, Object>> goodsContractList = new ArrayList<>();
        for (Map<String, Object> contractGoods : contractGoodsList) {
            Map<String, Object> goodsContract = new HashMap<>();
            goodsContract.put("name", contractGoods.get("name"));
            goodsContract.put("brand", contractGoods.get("brand"));
            goodsContract.put("model", contractGoods.get("model"));
            goodsContract.put("spec", contractGoods.get("spec"));
            goodsContract.put("description", contractGoods.get("description"));
            goodsContract.put("price", BigDecimalUtils.round(BigDecimalUtils.isNull(contractGoods.get("price")), 6));
            goodsContract.put("pretax_price", BigDecimalUtils.round(BigDecimalUtils.isNull(contractGoods.get("pretax_price")), 6));
            goodsContract.put("tax_rate", BigDecimalUtils.round(BigDecimalUtils.isNull(contractGoods.get("tax_rate")), 2));
            goodsContract.put("num", contractGoods.get("num"));
            goodsContract.put("id", contractGoods.get("id"));
            goodsContract.put("unit", contractGoods.get("unit"));

            goodsContract.put("golden_tax", "");
            goodsContract.put("unspsc", "");
            goodsContract.put("delivery", 0);
            goodsContract.put("package_unit", "");
            goodsContract.put("package_quantity", 0.0);
//            goodsContract.put("tax_rate_freight", 0.0);
            goodsContract.put("pretax_freight", 0.0);
            goodsContract.put("freight", 0.0);
//            goodsContract.put("tax_payable_freight", 0.0);
            BigDecimal pretaxAmount = BigDecimalUtils.calculateTaxBefore(BigDecimalUtils.isNull(contractGoods.get("total")),
                    BigDecimalUtils.mul(BigDecimalUtils.isNull(contractGoods.get("tax_rate")), new BigDecimal("100")));
            goodsContract.put("pretax_amount", pretaxAmount);
            goodsContract.put("amount", contractGoods.get("total"));
            goodsContract.put("pretax_total", pretaxAmount);
            goodsContract.put("total", contractGoods.get("total"));
//            goodsContract.put("contract_goods_id", contractGoods.get("id"));
            goodsContractList.add(goodsContract);
        }
//        BoServiceUtils.createBo(ModelConst.T_CONTRACT_GOODS, goodsContractList);
        return goodsContractList;
    }

    /**
     * 创建代购条款
     *
     * @param intentionId
     * @param contractClauseList
     * @param goodsAmount
     */
    public SingleResponse<BO> createContractClause(String intentionId, List<ContractClauseDto> contractClauseList, BigDecimal goodsAmount) {
        Assert.notNull(goodsAmount, "商品金额不能为空");
//        Assert.isTrue(BigDecimal.compare(goodsAmount, 0.0) == 1, "商品金额必须大于0");
        Assert.notNull(intentionId, "代购意向ID不能为空");
        Assert.isTrue(!CollectionUtils.isEmpty(contractClauseList), "代购条款不能为空");

//        List<Map<String, Object>> existContractClauseList = Collections.emptyList();

        List<String> ids = contractClauseList
                .stream().map(ContractClauseDto::getId).filter(StringUtils::isNotBlank).collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(ids)) {
            String idsSql = ids.stream().map(s -> "\'" + s + "\'").collect(Collectors.joining(", "));
            String sql = "delete from " + getTableName(ModelConst.T_CONTRACT_CLAUSE) + " where deleted ='0' and id in (" + idsSql + ")";
            jdbcTemplate.update(sql, new HashMap<>());
        }

        List<ContractClauseDto> saveAll = new ArrayList<>();
        BigDecimal verifyClause = BigDecimal.ZERO;
        for (ContractClauseDto contractClause : contractClauseList) {
            Assert.notNull(contractClause.getClauseRatio(), "条款比例 不能为空");

            BigDecimal clauseRatio = BigDecimalUtils.div(contractClause.getClauseRatio(), BigDecimal.ONE);
            verifyClause = BigDecimalUtils.add(verifyClause, clauseRatio);

            contractClause.setClauseRatio(clauseRatio);

//            //修改
//            if (!StringUtils.isBlank(contractClause.getId())) {
//                Map<String, Object> existContractClause = existContractClauseList.stream()
//                        .filter(t -> t.get("id").equals(contractClause.getId())).findFirst().orElseThrow(RuntimeException::new);
//
//                BeanUtils.copyProperties(contractClause, existContractClause, ClassUtils.getNullPropertyNames(contractClause));
//                BeanUtils.copyProperties(existContractClause, contractClause);
//            }
//            //新增
//            else {
//                contractClause.setContractIntentionId(intentionId);
//            }
            //新增
            contractClause.setContractIntentionId(intentionId);

            saveAll.add(contractClause);
        }

        Assert.isTrue(verifyClause.compareTo(BigDecimal.ONE) == 0, "分期比例必须满足100");

        saveAll = clauseCalculation(saveAll, goodsAmount);
        removeContractClause(intentionId, ids);

        List<Map<String, Object>> listMap = new ArrayList<>();
        for (ContractClauseDto dto : saveAll) {
            Map<String, Object> map = ContractClauseDto.voToEntity(dto);
            listMap.add(map);
        }
        return BoServiceUtils.createBo(ModelConst.T_CONTRACT_CLAUSE, listMap);
    }

    /**
     * 创建代购商品
     *
     * @param intentionId
     * @param contractGoodsList
     * @return
     */
    public List<Map<String, Object>> createContractGoods(String intentionId, List<ContractGoodsDto> contractGoodsList) {
        Assert.notNull(intentionId, "代购商品ID为null");
        Assert.isTrue(!CollectionUtils.isEmpty(contractGoodsList), "代购商品不存在");

//        List<Map<String, Object>> existContractGoodsList = Collections.emptyList();

        List<String> ids = contractGoodsList
                .stream().map(ContractGoodsDto::getId).filter(StringUtils::isNotBlank).collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(ids)) {
            String idsSql = ids.stream().map(s -> "\'" + s + "\'").collect(Collectors.joining(", "));
            String sql = "delete from " + getTableName(ModelConst.T_CONTRACT_GOODS) + " where deleted ='0' and id in (" + idsSql + ")";
            jdbcTemplate.update(sql, new HashMap<>());
        }

        List<ContractGoodsDto> saveAll = new ArrayList<>();
        for (ContractGoodsDto contractGoods : contractGoodsList) {

            Assert.isTrue(BigDecimalUtils.isNull(contractGoods.getPrice()).compareTo(BigDecimal.ZERO) == 1, "商品含税单价必须大于0");
            Assert.isTrue(BigDecimalUtils.isNull(contractGoods.getNum()).compareTo(BigDecimal.ZERO) == 1, "商品数量必须大于0");

            //修改
//            if (StringUtils.isNotBlank(contractGoods.getId())) {
//                Map<String, Object> existContractGoods = existContractGoodsList.stream()
//                        .filter(t -> t.get("id").equals(contractGoods.getId())).findFirst().orElseThrow(RuntimeException::new);
//
//                BeanUtils.copyProperties(contractGoods, existContractGoods, ClassUtils.getNullPropertyNames(contractGoods));
//                BeanUtils.copyProperties(existContractGoods, contractGoods);
//            }
//            //新增
//            else {
//                contractGoods.setContractIntentionId(intentionId);
//            }
            //新增
            contractGoods.setContractIntentionId(intentionId);

            contractGoods.setTaxRate(null != contractGoods.getTaxRate() ? BigDecimalUtils.div(BigDecimalUtils.isNull(contractGoods.getTaxRate()), BigDecimal.ONE) : new BigDecimal("0.16"));
            saveAll.add(contractGoods);
        }

        saveAll = goodsCalculation(saveAll);
        removeContractGoods(intentionId, ids);
        List<Map<String, Object>> listMap = new ArrayList<>();
        for (ContractGoodsDto contractGoodsDto : saveAll) {
            Map<String, Object> map = ContractGoodsDto.voToEntity(contractGoodsDto);
            listMap.add(map);
        }
        BoServiceUtils.createBo(ModelConst.T_CONTRACT_GOODS, listMap);
        return listMap;
    }

    /**
     * @param params
     * @return
     */
    private List<ContractGoodsDto> goodsCalculation(List<ContractGoodsDto> params) {
        List<ContractGoodsDto> results = new ArrayList<>();
        for (ContractGoodsDto param : params) {
            BigDecimal total = BigDecimalUtils.round(BigDecimalUtils.mul(param.getPrice(), param.getNum()), 2);
            BigDecimal pretaxPrice = BigDecimalUtils.calculateTaxBefore(param.getPrice(), param.getTaxRate());
            param.setTotal(total);
            param.setPretaxPrice(pretaxPrice);
            results.add(param);
        }
        return results;
    }

    private List<ContractClauseDto> clauseCalculation(List<ContractClauseDto> params, BigDecimal goodsAmount) {
        List<ContractClauseDto> results = new ArrayList<>();
        for (ContractClauseDto param : params) {
            param.setTotal(BigDecimalUtils.round(BigDecimalUtils.mul(goodsAmount, param.getClauseRatio()), 4));
            results.add(param);
        }
        return results;
    }

    /**
     * 标记删除商品.
     * 根据代购意向ID获取所有代购商品（忽略商品ID{@code ignoreIds}）,并进行标记删除
     *
     * @param intentionId 代购意向ID
     * @param ignoreIds   忽略删除的商品ID
     */
    private void removeContractGoods(String intentionId, List<String> ignoreIds) {
        String tableName = getTableName(ModelConst.T_CONTRACT_GOODS);
        String sql = "select * from " + tableName + " where deleted ='0' and contract_intention_id = '" + intentionId + "'";
        List<Map<String, Object>> contractGoodsList = jdbcTemplate.queryForList(sql, new HashMap<>());
        if (CollectionUtils.isEmpty(contractGoodsList)) {
            return;
        }

        if (CollectionUtils.isEmpty(ignoreIds)) {
            ignoreIds = Collections.emptyList();
        }

        List<String> finalIgnoreIds = ignoreIds;

        contractGoodsList = contractGoodsList.stream().filter(t -> !finalIgnoreIds.contains(t.get("id"))).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(contractGoodsList)) {
            return;
        }
        List<String> contractGoodsIds = contractGoodsList.stream().map(s -> (String) s.get("id")).collect(Collectors.toList());
        BoServiceUtils.batchDeleteBO(ModelConst.T_CONTRACT_GOODS, contractGoodsIds, true);
    }

    /**
     * 标记删除条款.
     * 根据代购意向ID获取所有代购条款（忽略条款ID{@code ignoreIds}）,并进行标记删除
     *
     * @param intentionId 代购意向ID
     * @param ignoreIds   忽略删除的条款ID
     */
    private void removeContractClause(String intentionId, List<String> ignoreIds) {
        String tableName = getTableName(ModelConst.T_CONTRACT_CLAUSE);
        String sql = "select * from " + tableName + " where deleted ='0' and contract_intention_id = '" + intentionId + "'";
        List<Map<String, Object>> contractClauseList = jdbcTemplate.queryForList(sql, new HashMap<>());
        if (CollectionUtils.isEmpty(contractClauseList)) {
            return;
        }

        if (CollectionUtils.isEmpty(ignoreIds)) {
            ignoreIds = Collections.emptyList();
        }

        List<String> finalIgnoreIds = ignoreIds;

        contractClauseList = contractClauseList.stream().filter(t -> !finalIgnoreIds.contains(t.get("id"))).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(contractClauseList)) {
            return;
        }
        List<String> contractClauseIds = contractClauseList.stream().map(s -> (String) s.get("id")).collect(Collectors.toList());
        BoServiceUtils.batchDeleteBO(ModelConst.T_CONTRACT_CLAUSE, contractClauseIds, true);
    }

    /**
     * 获取客户账期或供应商账期（结算账户账期）
     *
     * @return
     */
    public Integer getStatementCycle(String userId) {
        if (StringUtils.isBlank(userId)) {
            userId = RequestContext.getCorpLoginId();
        }
        UserDto userDto = UserUtils.getUserByUserId(userId);
        OrganizationDto organization = JdbcTemplateUtils.builder(AppConst.SYSTEM_MANAGEMENT, ModelConst.T_ORGANIZATION)
                .selectField("*").eq("id", userDto.getOrganization_id().get(0).getId()).queryForPOJO(OrganizationDto.class);
        if(null == organization){
            throw new RuntimeException("请联系平台管理员添加供应商结算组织！");
        }
        OrganizationDto transactionOrganization = JdbcTemplateUtils.builder(AppConst.SYSTEM_MANAGEMENT, ModelConst.T_ORGANIZATION)
                .selectField("*").eq("id", organization.getTransaction_organization_id().get(0).getId()).queryForPOJO(OrganizationDto.class);
        if (null != transactionOrganization) {
            return transactionOrganization.getStatement_cycle();
        }
        return 0;
    }
}
